home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 134_01.zip / CORO1.C < prev    next >
Text File  |  1993-06-12  |  7KB  |  280 lines

  1. /*    CORO1.C -- Coroutine package for BDS C
  2.  
  3. Copyright (c) 1983 by Kevin B. Kenny
  4.  
  5. Released to the BDS C Users' Group, Inc. for non-commercial distribution
  6.  
  7.     Kevin Kenny
  8.     729-A E. Cochise Dr.
  9.     Phoenix, Arizona   85020
  10.  
  11.     This file comprises the portions of the BDS C coroutine
  12. package that are implemented in C.
  13.  
  14. c_call        Call another coroutine
  15. c_callby    Change the current coroutine's caller
  16. c_caller    Find the current coroutine's caller
  17. c_create    Create a coroutine
  18. c_destroy    Destroy a coroutine (works only if ALLOC_ON defined)
  19. c_detach    Return to the coroutine that called this one.
  20. c_getinfo    Retrieve information specified by coroutine's creator.
  21. c_passer    Find coroutine that last invoked current one.
  22. c_resume    Lateral transfer to another coroutine.
  23. c_setinfo    Change information originally specified by creator.
  24. c_type        Find out how current coroutine was invoked.
  25. c_wmi        Find current coroutine (Who aM I?)
  26.  
  27.     Refer to the accompanying documentation for a detailed description
  28. of these functions.
  29. */
  30.  
  31. #include <bdscio.h>
  32. #include <coro.h>
  33.  
  34. /* CALL -- Call another coroutine, possibly passing a value */
  35.  
  36. /*  Usage:
  37.     retval = c_call (fcv, passval);
  38.     Where:
  39.     fcv    is a pointer to the target coroutine's FCV.
  40.     passval    is passed as a value to the target coroutine.
  41.     retval    is the value passed on the next invocation of this
  42.         coroutine (usually via c_detach)
  43. */
  44.  
  45. int c_call (fcv, passval) 
  46.     C_FCV * fcv; int passval;
  47.     {
  48.     fcv -> cf_caller_ = c_wmi ();    /* Set target's caller */
  49.     fcv -> cf_type_ = CT_CALL;        /* Set transfer type */
  50.     return (corpass (fcv, passval));    /* Do the transfer */
  51.     }
  52.  
  53.  
  54. /* CALLBY -- Change the caller of the current coroutine */
  55.  
  56. /*  Usage:
  57.     c_callby (fcv);
  58.     Where:
  59.     fcv    is a pointer to the FCV of the coroutine that will become
  60.         the caller.
  61. */
  62.  
  63. int c_callby (fcv)
  64.     C_FCV * fcv;
  65.     {
  66.     c_wmi () -> cf_caller_ = fcv;
  67.     }
  68.  
  69.  
  70. /* CALLER -- Find the caller of the current co-routine */
  71.  
  72. /* Usage:
  73.     fcv = c_caller ();
  74.    Where:
  75.     fcv     (returned) is a pointer to the FCV of the current
  76.         co-routine's caller.
  77. */
  78.  
  79. C_FCV * c_caller ()
  80.     {
  81.     return (c_wmi () -> cf_caller_);    
  82.     }
  83.  
  84.  
  85. /* CREATE -- Create a coroutine */
  86.  
  87. /*  Usage:
  88.     fcv = c_create (funct, stack, info);
  89.     Where:
  90.     funct    is the "main program" (initial function entry) of the
  91.         coroutine.
  92.     stack    is the size of the coroutine's stack area in bytes.
  93.     info    is an information word (generally a pointer to a
  94.         static storage area) describing the coroutine.  It
  95.         can later be retrieved by "getinfo" or modified by "setinfo".
  96.     fcv    (returned) is a pointer to the newly-created coroutine's
  97.         FCV, or ERROR if the coroutine could not be created
  98.         because suficient memory space was not available.
  99. */
  100.  
  101. C_FCV * c_create (funct, stack, info)
  102.     int (*funct) ();
  103.     int stack;
  104.     int info;
  105.     {
  106.     union fcvp {
  107.         C_FCV * f;
  108.         char  * b;
  109.         int i;
  110.         } fcv;
  111.     struct c_initstk_ * istk;
  112.     int corstart ();        /* Coroutine starter */
  113.     char * sbrk ();            /* If coroutines are to be created,
  114.                        a different memory manager is
  115.                        used.  Make sure the right one
  116.                        is loaded. */
  117.  
  118.     fcv.b=alloc (stack + sizeof *(fcv.f) + sizeof *istk);
  119.  
  120.     if (fcv.i == ERROR) return (ERROR);
  121.     
  122.     setmem (fcv.b, stack + sizeof *(fcv.f) + sizeof *istk, 0);
  123.                     /* Clear the FCV and stack */
  124.  
  125.     /* Set the stack size and stack pointer words in the fcv, and
  126.        build the initial stack content */
  127.  
  128.     (fcv.f) -> cf_stksiz_ = stack + sizeof *istk + sizeof *(fcv.f);
  129.     istk = (fcv.f) -> cf_sp_ = fcv.i + sizeof *(fcv.f) + stack;
  130.     istk -> ci_initfn_ = funct;
  131.     istk -> ci_start_ = &corstart;
  132.     
  133.     /* Build the user-specified information word and caller linkage.
  134.        Passer will be set the first time the coroutine is called. */
  135.  
  136.     (fcv.f) -> cf_caller_ = c_wmi ();
  137.     (fcv.f) -> cf_info_ = info;
  138.  
  139.     return (fcv.f);
  140.     }
  141.  
  142. /* DESTROY -- Destroy a coroutine */
  143.  
  144. /* Usage:
  145.     destroy (fcv);
  146.    Where:
  147.     fcv    is a pointer to the fcv of the coroutine to be
  148.         destroyed.
  149. */
  150.  
  151. int c_destroy (fcv)
  152.     C_FCV *fcv;
  153.     {
  154.     free (fcv);
  155.     }
  156.  
  157. /* DETACH -- Return to the coroutine that called this one */
  158.  
  159. /* Usage:
  160.     retval = c_detach (passval);
  161.    Where:
  162.     passval    is passed as a value to the coroutine that called
  163.         the present one.
  164.     retval    is the value passed on the next call to the present
  165.         coroutine.
  166. */
  167.  
  168. int c_detach (passval)
  169.     int passval;
  170.     {
  171.     C_FCV *fcv;
  172.     fcv = c_caller ();
  173.     fcv -> cf_type_ = CT_DETACH;
  174.     return (corpass (fcv, passval));
  175.     }
  176.  
  177. /* GETINFO -- Get information specified about a coroutine */
  178.  
  179. /* Usage:
  180.     info = c_getinfo (fcv);
  181.    Where:
  182.     fcv    is a pointer to the FCV of the coroutine to query.
  183.     info    is the "info" word set in the FCV by "create" or "setinfo".
  184.    Notes:
  185.     The "info" word is designed to keep coroutine-local static storage.
  186.     It will generally be a pointer to the static storage area.
  187. */
  188.  
  189. int c_getinfo (fcv)
  190.     C_FCV * fcv;
  191.     {
  192.     return (fcv -> cf_info_);
  193.     }
  194.  
  195. /* PASSER -- Find coroutine that last transferred control to us. */
  196.  
  197. /* Usage:
  198.     fcv = c_passer ();
  199.    Where:
  200.     fcv    is a pointer to the FCV of the coroutine that last
  201.         transferred control to the present one by any means.
  202. */
  203.  
  204. C_FCV * c_passer () {
  205.     return (c_wmi() -> cf_passer_);
  206.     }
  207.  
  208. /* RESUME -- GO TO another coroutine, inheriting caller */
  209.  
  210. /* Usage:
  211.     retval = c_resume (fcv, passval);
  212.    Where:
  213.     fcv    is a pointer to the FCV of the coroutine to be
  214.         resumed.  If this coroutine DETACHes, iut
  215.         will return to the caller of the coroutine
  216.         that did the C_RESUME.
  217.     passval    is the value to pass to the target coroutine.
  218.     retval    is the value passed on the next invocation of the
  219.         present coroutine.
  220. */
  221.  
  222. int c_resume (fcv, passval)
  223.     C_FCV *fcv; int passval;
  224.     {
  225.     fcv -> cf_caller_ = c_wmi() -> cf_caller_;
  226.     fcv -> cf_type_ = CT_RESUME;
  227.     return (corpass (fcv, passval));
  228.     }
  229.  
  230. /* SETINFO -- Change the "info" word in FCV */
  231.  
  232. /* Usage:
  233.     setinfo (fcv, info);
  234.    Where:
  235.     fcv    is a pointer to the FCV of the coroutine to be altered.
  236.     info    is the new content of the "info" word.
  237. */
  238.  
  239. int c_setinfo (fcv, info)
  240.     C_FCV * fcv;
  241.     int info;
  242.     {
  243.     return (fcv -> cf_info_ = info);
  244.     }
  245.  
  246. /* TYPE -- Find out how the current coroutine was invoked */
  247.  
  248. /* Usage
  249.     type = c_type ();
  250.    Where:
  251.     type is one of the following values:
  252.         0 Unknown how we got here.
  253.         1 C_CALL
  254.         2 C_RESUME
  255.         3 C_DETACH
  256.         4 A called coroutine "fell off the end".
  257. */
  258.  
  259. int c_type () {
  260.     return (c_wmi () -> cf_type_);
  261.     }
  262.  
  263. /* WMI -- Find current coroutine's FCV (Who aM I?) */
  264.  
  265. /* Usage:
  266.     fcv = c_wmi ();
  267.    Where:
  268.     fcv    is returned as a pointer to the current coroutine's
  269.         FCV.
  270. */
  271.  
  272. C_FCV * c_wmi () {
  273.     C_FCV **corwmip();
  274.     return (*corwmip());
  275.     }
  276. _FCV *fcv; int passval;
  277.     {
  278.     fcv -> cf_caller_ = c_wmi() -> cf_caller_;
  279.     fcv -> cf_type_ = CT_RESUME;
  280.